package me.spring.cloud.common.components.oauth2.token.handle;

import me.spring.cloud.common.components.oauth2.token.store.RedisTokenStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

/**
 * @author Luffy
 * @description: TODO
 * @date 2019-3-26 18:00
 */
public class OAuth2TokenHandle {

    private static final Logger logger = LoggerFactory.getLogger(OAuth2TokenHandle.class);

    /**
     *
     * @Author Luffy
     * @Description 清除token信息
     * @Date 18:04 2019/3/26
     * @Param [tokenStore, request]
     * @Return void
     **/
    public static void reMoveToken(TokenStore tokenStore, HttpServletRequest request){
        String token = extractToken(request);
        Assert.hasText(token, "token must be set");
        OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token);
        if (existingAccessToken != null) {
            if (existingAccessToken.getRefreshToken() != null) {
                logger.info("remove refreshToken!", existingAccessToken.getRefreshToken());
                OAuth2RefreshToken refreshToken = existingAccessToken.getRefreshToken();
                tokenStore.removeRefreshToken(refreshToken);
            }
            logger.info("remove existingAccessToken!", existingAccessToken);
            tokenStore.removeAccessToken(existingAccessToken);
        }
    }

    /**
     *
     * @Author Luffy
     * @Description 清除token信息(通过uname_to_access)
     * @Date 10:21 2019/5/8
     * @Param [tokenStore, clientId, username]
     * @Return void
     **/
    public static void removeTokenByUserName(RedisTokenStore redisTokenStore, String userName){
       redisTokenStore.removeTokenByUserName(userName);
    }

    private static String extractToken(HttpServletRequest request) {
        String token = extractHeaderToken(request);
        if (token == null) {
            logger.debug("Token not found in headers. Trying request parameters.");
            token = request.getParameter("access_token");
            if (token == null) {
                logger.debug("Token not found in request parameters.  Not an OAuth2 request.");
            } else {
                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, "Bearer");
            }
        }

        return token;
    }

    private static String extractHeaderToken(HttpServletRequest request) {
        Enumeration headers = request.getHeaders("Authorization");

        String value;
        do {
            if (!headers.hasMoreElements()) {
                return null;
            }
            value = (String) headers.nextElement();
        } while (!value.toLowerCase().startsWith("Bearer".toLowerCase()));

        String authHeaderValue = value.substring("Bearer".length()).trim();
        request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, value.substring(0, "Bearer".length()).trim());
        int commaIndex = authHeaderValue.indexOf(44);
        if (commaIndex > 0) {
            authHeaderValue = authHeaderValue.substring(0, commaIndex);
        }

        return authHeaderValue;
    }
}
